--[[
CastYeller2 - Announce important spell events.

Copyright (C) 2009 Adirelle

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--]]

if not CastYeller2 then return end
local CastYeller2 = CastYeller2 

local L = CastYeller2.L
local defaultAnnouncesDB = CastYeller2.defaultAnnouncesDB

local _, class = UnitClass('player')
local locale = GetLocale()

--------------------------------------------------------------------------------
-- Spell name cache
--------------------------------------------------------------------------------

local N = setmetatable({}, {__mode='kv', __index = function(self, key)
	local name = key and tonumber(key) and GetSpellInfo(tonumber(key)) or key
	self[key] = name
	return name
end})

--------------------------------------------------------------------------------
-- Custom announces
--------------------------------------------------------------------------------

local C
--[===[@debug@
C = {
	HUNTER = {
		['Misdirection:buffApplied'] = "Misdirection on $TARGET\n$TARGET has been misdirected",
		['Freezing Trap:debuffApplied'] = "$TARGET is frozen !\n$TARGET got a cold",
	},
}
--@end-debug@]===]
--@non-debug@
if locale == 'enUS' then
	C =	{
	HUNTER = {
		["Wyvern Sting:debuffApplied"] = "Wyvern Sting:debuffApplied",
	},
}

elseif locale == 'frFR' then
	C = {
	HUNTER = {
		["Wyvern Sting:debuffApplied"] = [=[$TARGET va faire un petit somme !
$TARGET, tes paupi\195\168res sont lourdes ! Dors, je le veux !]=],
	},
}

elseif locale == "deDE" then
	C = {
	HUNTER = {
		-- ["Wyvern Sting:debuffApplied"] = "",
	},
}

elseif locale == "esMX" then
	C = {
	HUNTER = {
		-- ["Wyvern Sting:debuffApplied"] = "",
	},
}

elseif locale == "ruRU" then
	C = {
	HUNTER = {
		-- ["Wyvern Sting:debuffApplied"] = "",
	},
}

elseif locale == "esES" then
	C = {
	HUNTER = {
		-- ["Wyvern Sting:debuffApplied"] = "",
	},
}

elseif locale == "zhTW" then
	C = {
	HUNTER = {
		["Wyvern Sting:debuffApplied"] = "奇美拉釘刺:減益已施加",
	},
}

elseif locale == 'zhCN' then
	C = {
	HUNTER = {
		-- ["Wyvern Sting:debuffApplied"] = "",
	},
}

elseif locale == 'koKR' then
	C = {
	HUNTER = {
		["Wyvern Sting:debuffApplied"] = "비룡 쐐기:디버프적용",
	},
}

end	
--@end-non-debug@

--------------------------------------------------------------------------------
-- Declaration helper
--------------------------------------------------------------------------------

local AnnounceBuilder = {}

-- Create a new announce
function AnnounceBuilder:Declare(id, ...)
	local name = N[id]
	local announce = { names = { [name] = true } } 
	for i = 1, select('#', ...) do	
		announce.names[N[select(i, ...)]] = true
	end
	self.announce = announce
	defaultAnnouncesDB[name] = announce
	return self
end

-- Make this API public
function CastYeller2:DeclareDefaultAnnounce(...)
	return AnnounceBuilder:Declare(...)
end

-- Declare the triggers (and sources) of the announce
function AnnounceBuilder:TriggersOn(...)
	self.announce.sources = { ['*'] = false }
	self.announce.triggers = { ['*'] = false }
	for i = 1, select('#', ...) do
		local source, trigger = tostring(select(i, ...)):match('^(.+)%.(.+)$')
		if source and trigger then
			self.announce.sources[source] = true
			self.announce.triggers[trigger] = true
		end
	end
	return self
end

-- Restrict announce to combat
function AnnounceBuilder:OnlyInCombat()
	self.announce.inCombat = true
	return self
end

-- Declare spell that can only be cast on self
function AnnounceBuilder:AlwaysTargetsSelf()
	self.announce.targetting = "self"
	return self
end

-- Declare untargetted spell
function AnnounceBuilder:NoTarget()
	self.announce.targetting = "none"
	return self
end

-- Fetch localized custom announces
function AnnounceBuilder:WithCustomAnnounces(name, namespace)
	local strings = C and C[namespace or class]
	if not strings then return end
	local announce = self.announce
	for trigger in pairs(announce.triggers) do
		local key = name..':'..trigger
		local customs = strings[key]
		if type(customs) == "string" and customs ~= key and customs:trim() ~= "" then
			local list = {}
			if not announce.custom then
				announce.custom = {}
			end
			announce.custom[trigger] = { enabled = true, announces = list }
			for line in customs:gmatch("[^\n]+") do
				table.insert(list, line:trim())
			end
		end
	end
	return self
end

-- Disable the announce by default
function AnnounceBuilder:Disabled()
	self.announce.enabled = false
	return self
end

--------------------------------------------------------------------------------
-- Shortcuts
--------------------------------------------------------------------------------

local function DeclareCrowdControl(name, isInstant, hasCooldown, ...)
	AnnounceBuilder:Declare(...):TriggersOn(
		(isInstant and 'Spellcasts.instantCast' or 'Spellcasts.startCasting'),
		'Spellcasts.spellMiss',
		'Spellcasts.castFailure',
		'Auras.debuffApplied', 
		'Auras.debuffBroken', 
		'Auras.debuffRemoved',
		(hasCooldown and 'Cooldowns.cooldownEnd' or nil)
	):WithCustomAnnounces(name)
end

--------------------------------------------------------------------------------
if class == 'HUNTER' then
--------------------------------------------------------------------------------
	
	-- Misdirection
	AnnounceBuilder:Declare(34477):TriggersOn(
		'Spellcasts.instantCast',
		'Cooldowns.cooldownEnd',
		'Spellcasts.castFailure'
	):WithCustomAnnounces('Misdirection')
	
	-- Freezing Trap and Freezing Arrow, including their effects
	DeclareCrowdControl('Freezing Trap', true, true, 1499, 60192, 3355, 60210)
	
	-- Wyvern Sting
	DeclareCrowdControl('Wyvern Sting', true, true, 19386)
	
	-- Tranquilizing Shot
	AnnounceBuilder:Declare(19801):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure', 
		'Spellcasts.spellMiss',
		'Cooldowns.cooldownEnd'
	):OnlyInCombat():WithCustomAnnounces('Tranquilizing Shot')

--------------------------------------------------------------------------------
elseif class == 'DRUID' then
--------------------------------------------------------------------------------

	-- Innervate
	AnnounceBuilder:Declare(29166):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure',
		'Cooldowns.cooldownEnd'
	):OnlyInCombat():WithCustomAnnounces('Innervate')

	-- Rebirth
	AnnounceBuilder:Declare(20484):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure', 
		'Cooldowns.cooldownEnd'
	):OnlyInCombat():WithCustomAnnounces('Rebirth')

	-- Hibernate
	DeclareCrowdControl('Hibernate', false, false, 2637)

	-- Cyclone
	DeclareCrowdControl('Cyclone', false, false, 33786)

	-- Tranquility
	AnnounceBuilder:Declare(740):TriggersOn(
		'Spellcasts.startCasting',
		'Spellcasts.castFailure',
		'Cooldowns.cooldownEnd'
	):OnlyInCombat():WithCustomAnnounces('Tranquility')

	-- Growl
	AnnounceBuilder:Declare(6795):TriggersOn(
		'Spellcasts.spellMiss',
		'Spellcasts.castFailure'
	):OnlyInCombat():WithCustomAnnounces('Growl')

	-- Challenging Roar
	AnnounceBuilder:Declare(5209):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure', 
		'Spellcasts.spellMiss',
		'Cooldowns.cooldownEnd'
	):OnlyInCombat():WithCustomAnnounces('Challenging Roar')

	-- Revive
	AnnounceBuilder:Declare(50769):TriggersOn(
		'Spellcasts.startCasting'
	):WithCustomAnnounces('Revive')

	-- Survival Instincts
	AnnounceBuilder:Declare(61336):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure',
		'Cooldowns.cooldownEnd'
	):AlwaysTargetsSelf():OnlyInCombat():WithCustomAnnounces('Survival Instincts')

--------------------------------------------------------------------------------
elseif class == 'MAGE' then
--------------------------------------------------------------------------------

	-- Polymorph
	DeclareCrowdControl('Polymorph', false, false, 118, 28272, 28271)

	-- Counterspell
	AnnounceBuilder:Declare(2139):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure',
		'Spellcasts.spellMiss',
		'Cooldowns.cooldownEnd'
	):OnlyInCombat():WithCustomAnnounces('Counterspell')

	-- Portal
	AnnounceBuilder:Declare(11419, 32266, 11416, 11417, 33691, 32267, 49361, 10059, 49360, 11420, 11418, 53142):TriggersOn(
		'Spellcasts.startCasting'
	):WithCustomAnnounces('Portal')

	-- Spellsteal
	AnnounceBuilder:Declare(30449):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure',
		'Spellcasts.spellMiss'
	):OnlyInCombat():WithCustomAnnounces('Spellsteal')

	-- Ritual of Refreshment
	AnnounceBuilder:Declare(43987):TriggersOn(
		'Spellcasts.startCasting'
	):WithCustomAnnounces('Ritual of Refreshment')

--------------------------------------------------------------------------------
elseif class == 'PALADIN' then
--------------------------------------------------------------------------------

	-- Divine Intervention
	AnnounceBuilder:Declare(19752):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure',
		'Cooldowns.cooldownEnd'
	):OnlyInCombat():WithCustomAnnounces('Divine Intervention')

	-- Hand of Protection
	AnnounceBuilder:Declare(1022):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure',
		'Cooldowns.cooldownEnd'
	):OnlyInCombat():WithCustomAnnounces('Hand of Protection')

	-- Repentance
	DeclareCrowdControl('Repentance', true, true, 20066)

	-- Redemption
	AnnounceBuilder:Declare(7328):TriggersOn(
		'Spellcasts.startCasting'
	):WithCustomAnnounces('Redemption')

	-- Lay on Hands
	AnnounceBuilder:Declare(633):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure',
		'Cooldowns.cooldownEnd'
	):OnlyInCombat():WithCustomAnnounces('Lay on Hands')

--------------------------------------------------------------------------------
elseif class == 'PRIEST' then
--------------------------------------------------------------------------------

	-- Shackle Undead
	DeclareCrowdControl('Shackle Undead', false, false, 9484)

	-- Resurrection
	AnnounceBuilder:Declare(2006):TriggersOn(
		'Spellcasts.startCasting'
	):WithCustomAnnounces('Resurrection')

	-- Mind Control
	DeclareCrowdControl('Mind Control', false, false, 605)

--------------------------------------------------------------------------------
elseif class == 'ROGUE' then
--------------------------------------------------------------------------------

	-- Kick
	AnnounceBuilder:Declare(1766):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure',
		'Spellcasts.spellMiss',
		'Cooldowns.cooldownEnd'
	):OnlyInCombat():WithCustomAnnounces('Kick')

	-- Sap
	DeclareCrowdControl('Sap', true, false, 6770)

	-- Blind
	DeclareCrowdControl('Blind', true, true, 2094)

--------------------------------------------------------------------------------
elseif class == 'SHAMAN' then
--------------------------------------------------------------------------------

	-- Mana Tide Totem
	AnnounceBuilder:Declare(16190):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure'
	):OnlyInCombat():WithCustomAnnounces('Mana Tide Totem')

	-- Bloodlust/Heroism
	AnnounceBuilder:Declare(2825, 32182):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure'
	):OnlyInCombat():WithCustomAnnounces('Bloodlust')
	
	-- Ancestral Spirit
	AnnounceBuilder:Declare(2008):TriggersOn(
		'Spellcasts.startCasting'	
	):WithCustomAnnounces('Ancestral Spirit')

	-- Hex
	DeclareCrowdControl('Hex', false, true, 51514)

--------------------------------------------------------------------------------
elseif class == 'WARLOCK' then
--------------------------------------------------------------------------------

	-- Ritual of Souls
	AnnounceBuilder:Declare(29893):TriggersOn(
		'Spellcasts.startCasting'
	):WithCustomAnnounces('Ritual of Souls')

	-- Ritual of Summoning
	AnnounceBuilder:Declare(29893):TriggersOn(
		'Spellcasts.startCasting'
	):WithCustomAnnounces('Ritual of Summoning')

	-- Fear
	DeclareCrowdControl('Fear', false, false, 29893)
	
	-- Banish
	DeclareCrowdControl('Banish', false, false, 710)
	
--------------------------------------------------------------------------------
elseif class == 'WARRIOR' then
--------------------------------------------------------------------------------

	-- Challenging Shout
	AnnounceBuilder:Declare(1161):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure'
	):OnlyInCombat():WithCustomAnnounces('Challenging Shout')

	-- Shield Wall
	AnnounceBuilder:Declare(871):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure'
	):OnlyInCombat():WithCustomAnnounces('Shield Wall')

	-- Last Stand
	AnnounceBuilder:Declare(12975):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure'
	):AlwaysTargetsSelf():OnlyInCombat():WithCustomAnnounces('Last Stand')

	-- Taunt
	AnnounceBuilder:Declare(355):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure',
		'Spellcasts.spellMiss'
	):OnlyInCombat():WithCustomAnnounces('Taunt')

	-- Mocking Blow
	AnnounceBuilder:Declare(694):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure',
		'Spellcasts.spellMiss'
	):OnlyInCombat():WithCustomAnnounces('Mocking Blow')

	-- Pummel
	AnnounceBuilder:Declare(6552):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure',
		'Spellcasts.spellMiss'
	):OnlyInCombat():Disabled():WithCustomAnnounces('Pummel')

	-- Shield Bash
	AnnounceBuilder:Declare(72):TriggersOn(
		'Spellcasts.instantCast',
		'Spellcasts.castFailure',
		'Spellcasts.spellMiss'
	):OnlyInCombat():Disabled():WithCustomAnnounces('Shield Bash')

	-- Sunder Armor
	AnnounceBuilder:Declare(7386):TriggersOn(
		'Auras.debuffGain',
		'Spellcasts.castFailure'
	):OnlyInCombat():Disabled():WithCustomAnnounces('Sunder Armor')

end

-- Common announces

-- Summoning Stone Effect
AnnounceBuilder:Declare(59782):TriggersOn(
	'Spellcasts.startCasting'
):WithCustomAnnounces('Summoning Stone Effect')

